	//---------------------------------------------------------------------
	// Includes
	//---------------------------------------------------------------------			
	#include <assert.h>
	#include <Libs/rgbe.h>
	#include <Rendering/Renderer.hpp>
	#include <Rendering/Texture.hpp>	
	#include <string>
	#include <Tools/Log.hpp>	
	#include <IL/il.h>
	#include <IL/ilu.h>
	#include <IL/ilut.h>
	
namespace Rendering {

	//---------------------------------------------------------------------
	// Texture manager methods	
	//---------------------------------------------------------------------
	TextureManager::TextureManager() {
		// Initalize DevIL
		ilInit();
		
		// Set image origin on the upper left corner
		ilOriginFunc(IL_ORIGIN_UPPER_LEFT);
		ilEnable(IL_ORIGIN_SET);

		// Force image loading on BGRA format
		ilSetInteger(IL_FORMAT_MODE, IL_RGBA);
		ilEnable(IL_FORMAT_SET);
	}
	//---------------------------------------------------------------------
	TextureManager&	TextureManager::Instance() {
		static TextureManager instance;
		return instance;
	}
	//---------------------------------------------------------------------	
	TITexturePointer TextureManager::CreateTexture(const std::string& filename, PixelFormat format) const {	
		// Generate image
		ILuint textureIL;
		ilGenImages(1, &textureIL);
		ilBindImage(textureIL);
 
		// Load image				
		ILstring file = const_cast<ILstring>(filename.c_str());
		ILboolean successLoading = ilLoadImage(file);

		// Chech loading error
		ILenum Error;
		while ((Error = ilGetError()) != IL_NO_ERROR)
			Tools::Error("Image loading error %d: %s", Error, iluErrorString(Error));
		assert(successLoading != IL_FALSE);
		
		// Get image's size
		int width, height;
		width = ilGetInteger(IL_IMAGE_WIDTH);
		height = ilGetInteger(IL_IMAGE_HEIGHT);

		// Get image's pixel
		void* pixels = ilGetData();
		
		// Create texture 
		int nLevels = 0;
		TRenderingID textureID = Renderer::Instance().CreateTexture(format, nLevels, width, height, pixels);
		TITexturePointer texture(new ITexture(SQUARE_TEXTURE, format, width, height, textureID));
		
		// Suppression de la texture
		ilBindImage(0);
		ilDeleteImages(1, &textureIL);
		
		return texture;
	}
	//---------------------------------------------------------------------	
	TITexturePointer TextureManager::CreateCubeTexture(const std::string filenames[6], PixelFormat format) const {
		// Generate image
		ILuint textureIL[6];
		ilGenImages(6, textureIL);
		
		// 		
		int width, height;
		const unsigned char* pixels[6];
		for(int imageIndex=0;imageIndex<6;++imageIndex) {
			// Load image				
			ilBindImage(textureIL[imageIndex]);
			ILstring file = const_cast<ILstring>(filenames[imageIndex].c_str());
			ILboolean successLoading = ilLoadImage(file);
			
			// Chech loading error
			ILenum Error;
			while ((Error = ilGetError()) != IL_NO_ERROR)
				Tools::Error("Image loading error %d: %s", Error, iluErrorString(Error));
			assert(successLoading != IL_FALSE);
			
			// Get image's size			
			width = ilGetInteger(IL_IMAGE_WIDTH);
			height = ilGetInteger(IL_IMAGE_HEIGHT);
			
			// Get image's pixel
			pixels[imageIndex] = ilGetData();
		}		

		// Create texture
		int nLevels = 0;
		TRenderingID textureID = Renderer::Instance().CreateCubeTexture(format, nLevels, width, height, pixels);
		TITexturePointer texture(new ITexture(CUBE_TEXTURE, format, width, height, textureID));
				
		// Suppression de la texture	
		ilDeleteImages(6, textureIL);
		return texture;
	}
	//---------------------------------------------------------------------	
	TextureManager::~TextureManager() {
		// Shut down Devil
		ilShutDown();
	}	
	//---------------------------------------------------------------------
	int TextureManager::GetMaxMipsMapLevel(int w, int h) {
        int count = 0;
        while ((w > 1) || (h > 1)) {
            if (w > 1)  w  /= 2;
            if (h > 1) h /= 2;
            ++count;
        }
        return count;
    }


	//---------------------------------------------------------------------
	// ITexture methods	
	//---------------------------------------------------------------------
	//ITexture::ITexture(PixelFormat f, int w, int h):
	//format(f),width(w),height(h) {
	//}	
	//---------------------------------------------------------------------
	ITexture::ITexture(TextureType t, PixelFormat f, int w, int h, TRenderingID id):
	type(t),format(f),width(w),height(h),textureID(id) {
	
	}
	//---------------------------------------------------------------------
	ITexture::~ITexture() {
		Renderer::Instance().DeleteTexture(textureID);
	}
	//---------------------------------------------------------------------
	void ITexture::Enable(int unit) const {
		Renderer::Instance().LoadTexture(textureID, type, unit);
	}
	//---------------------------------------------------------------------
	void ITexture::Disable(int unit) const {
		Renderer::Instance().LoadTexture(textureID, type, 0);
	}	
}
